﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SingletonPattern
{
    /// <summary>
    /// 线程安全模式
    /// </summary>
    /// <remarks>
    ///  以上方式的实现方式是线程安全的，首先我们创建了一个静态只读的进程辅助对象，由于lock是确保当一个线程位于代码的临界区时，另一个线程不能进入临界区（同步操作）。
    ///  如果其他线程试图进入锁定的代码，则它将一直等待，直到该对象被释放。
    ///  从而确保在多线程下不会创建多个对象实例了。只是这种实现方式要进行同步操作，这将是影响系统性能的瓶颈和增加了额外的开销。
    ///  
    /// </remarks>
    public sealed class SynSingleton
    {
        // 定义一个静态变量来保存类的实例
        private static SynSingleton _uniqueInstance = null;

        // 定义一个标识确保线程同步
        private static readonly object locker = new object();

        // 定义私有构造函数，使外界不能创建该类实例
        private SynSingleton()
        {
        }

        /// <summary>
        ///  // 定义公有属性来提供一个全局访问点,同时你也可以定义公有方法来提供全局访问点
        /// </summary>
        //public static SynSingleton Instance
        //{
        //    get
        //    {
        //        // 当第一个线程运行到这里时，此时会对locker对象 "加锁"，
        //        // 当第二个线程运行该方法时，首先检测到locker对象为"加锁"状态，该线程就会挂起等待第一个线程解锁
        //        // lock语句运行完之后（即线程运行完之后）会对该对象"解锁"
        //        lock (locker)
        //        {
        //            // 如果类的实例不存在则创建，否则直接返回
        //            // 如果类的实例不存在则创建，否则直接返回
        //            if (_uniqueInstance == null)
        //            {
        //                _uniqueInstance = new SynSingleton();
        //            }
                   
        //        }

        //        return _uniqueInstance;
        //    }
        //}

        //or

        ///// <summary>
        ///// 定义公有方法提供一个全局访问点,同时你也可以定义公有属性来提供全局访问点
        ///// </summary>
        ///// <returns></returns>
        public static SynSingleton GetInstance()
        {
            // 当第一个线程运行到这里时，此时会对locker对象 "加锁"，
            // 当第二个线程运行该方法时，首先检测到locker对象为"加锁"状态，该线程就会挂起等待第一个线程解锁
            // lock语句运行完之后（即线程运行完之后）会对该对象"解锁"
            lock (locker)
            {
                // 如果类的实例不存在则创建，否则直接返回
                if (_uniqueInstance == null)
                {
                    _uniqueInstance = new SynSingleton();
                }
            }

            return _uniqueInstance;
        }
    }
}
